package Twitim::NetBase;

use strict;
use warnings;

use LWP::UserAgent;
use HTTP::Date qw(str2time);
use POSIX qw(strftime);

my %My_ID;
my %Favorites;
my @Followers;
my $Users = {};
my $ua = LWP::UserAgent->new( env_proxy => 1 );
our $L10N = sub { my ( $text ) = @_; return $text; };

# account

sub credentials {
    my ( $self, $userid, $token, $secret ) = @_;

    $self->{'userid'}        = $userid;
    $self->{'access_token'}  = $token;
    $self->{'access_secret'} = $secret;

    $self->set_my_id($userid);
}

sub set_my_id {
    my ( $self, $id ) = @_;

    return if !defined $id;

    my $protocol = ( $id =~ /@/ ) ? 'xmpp' : 'twitter';
    $My_ID{$protocol} = $id;
    $My_ID{'default'} = $My_ID{'twitter'} || $My_ID{'xmpp'};
}

sub get_my_id {
    return $My_ID{'default'};
}

# error

sub get_error {
    my $self = shift;
    return $self->{'error'};
}

sub set_error {
    my ( $self, $text, $status_desc ) = @_;

    if ($text) {
        $self->{'error'} = $text;
    }
    else {
        delete $self->{'error'} if !$status_desc;
    }

    $self->{'cb'}->{'error'}->( $self->{'protocol'}, $text, $status_desc )
        if $self->{'cb'}->{'error'}
}

# users admin

sub set_username {
    my ( $self, $jid, $user_name ) = @_;
    return unless defined $user_name;

    $jid =~ tr/()//d;
    $Users->{$jid}->{'name'} = $user_name;
}

sub set_userid {
    my ( $self, $jid, $user_id ) = @_;
    return unless defined $user_id;

    $jid =~ tr/()//d;
    $Users->{$jid}->{'userid'} = $user_id;
}

sub set_icon {
    my ( $self, $jid, $image_url ) = @_;
    return unless defined $image_url;

    $jid =~ s/^Direct from $//;
    $jid =~ tr/()//d;

    utf8::decode($image_url) unless utf8::is_utf8($image_url);

    if ( $My_ID{'twitter'} && $jid eq $My_ID{'twitter'} ) {
        $My_ID{'icon'} = $image_url;
   }

    $Users->{$jid}->{'icon'} = $image_url;
}

sub get_my_icon_url {
    return $My_ID{'icon'};
}

sub get_username {
    my ( $self, $jid ) = @_;

    $jid =~ tr/()//d;

    if ( exists $Users->{$jid}->{'name'} && $Users->{$jid}->{'name'} ne $jid ) {
        $jid = "$jid ($Users->{$jid}->{'name'})";
    }

    return $jid;
}

sub get_userid {
    my ( $self, $jid ) = @_;
    my $userid;
    $userid = $Users->{$jid}->{'userid'} if exists $Users->{$jid}->{'userid'};
    return $userid;
}

sub set_follower {
    my ( $self, $followers_ref ) = @_;
    @Followers = @$followers_ref;
}

sub check_follower {
    my ( $self, $jid ) = @_;
    my $userid = $self->get_userid($jid);
    my $res = ($userid && grep /$userid/, @Followers) ? 1 : 0;
    return $res;
}

sub icon_is_ok {
    my ( $self, $jid ) = @_;
    return exists $Users->{$jid}->{'icon'};
}

sub get_icon {
    my ( $self, $jid, $image_size ) = @_;

    $jid =~ tr/()//d;
    return unless $Users->{$jid}->{'icon'};

    $image_size ||= 1; # normal size
    my $image_dir = "/tmp/twitim-$ENV{'USER'}/";

    unless ( -d $image_dir ) {
        mkdir $image_dir, oct(700);
    }

    my ( $image_file, $image_url_path );
    if ( $Users->{$jid}->{'icon'} =~ m{^(.*/)(.*?)$} ) {
        $image_url_path = $1;
        $image_file     = $2;
        $image_file =~ s{_normal\.}{_mini\.} if $image_size == 2; # mini size;
    }
    else {
        warn "oops!: $jid - $Users->{$jid}->{'icon'} \n";
        return 0;
    }

    my $image_prefix
        = ( $image_file =~ /^default_profile_.*\.png$/ ) ? "" : "$jid-";
    my $image_fullpath = $image_dir . $image_prefix . $image_file;

    unless ( -e $image_fullpath ) {
        utf8::encode($image_file);
        $image_file =~ s/([^\w ])/'%'.unpack('H2', $1)/eg;

        my $req = HTTP::Request->new( GET => "$image_url_path$image_file" );
        my ( $res, $timeout ) = $self->get_http($req);

        if ( $res->code == 200 ) {
            open my $fh, '>', $image_fullpath or die;
            print {$fh} $res->content;
            close $fh;
        }
        else {
            # warn $res->code . " $image_fullpath\n";

            my $default_image = 'default_profile_normal.png';
            $default_image =~ s{_normal\.}{_mini\.} if $image_size == 2;
            $image_fullpath = $image_dir . $default_image;

            return 0 if !-e $image_fullpath;
        }
    }

    return $image_fullpath;
}

sub get_color {
    my ( $self, $jid, $color_mode, $color_scheme ) = @_;

    $jid = $1 if $jid =~ /Direct from (\S+)/;
    $jid =~ tr/()//d;

    if ( !exists( $Users->{$jid}->{'color'} ) ) {
        my ( $color, $y, $s );
        my ( $lightest, $darkest )
            = $color_mode && $color_mode eq 'dark' ? ( 255, 50 ) : ( 150, 0 );

        do {
            my ( $red, $green, $blue );

            if ( !$color_scheme ) {
                $color = sprintf( "#%06x", int( rand(0xFFFFFF) ) );
                ( $red, $green, $blue ) = _hex2rgb($color);
            }
            else {
                $color = int( rand( 230 - 17 ) ) + 17;
                my $c = $color - 16;
                $red   = int( $c / 36 ) * 40 + 55;
                $green = int( ( $c % 36 ) / 6 ) * 40 + 55;
                $blue  = int( ( $c % 36 ) % 6 ) * 40 + 55;
            }

            ( $y, $s ) = get_bw( $red, $green, $blue );
        } while ( $y > $lightest || $y < $darkest || $s < 60 );
        $Users->{$jid}->{'color'} = $color;

        # print "$jid: $y - $s\n";
    }

    return $Users->{$jid}->{'color'};
}

sub get_bw {
    my ( $red, $green, $blue ) = @_;

    my @arr = sort { $a <=> $b } ( $red, $green, $blue );
    my ( $min, $max ) = ( $arr[0], $arr[-1] );
    my $s = $max - $min;

    my $y = $red * 0.29891 + $green * 0.58661 + $blue * 0.11448;

    return ( $y, $s );
}

# time

sub get_unixtime {
    my ( $self, $time ) = @_;

    my $unixtime = time;

    if ($time) {
        $time =~ s/\+0000/GMT/;
        $unixtime = str2time($time);
    }

    return $unixtime;
}

sub get_formatted_time {
    my ( $self, $unixtime ) = @_;

    my $time_format = '%T';
    $time_format = '%y-%m-%d' if time - $unixtime > 60 * 60 * 24;

    my $time_str = strftime($time_format, localtime($unixtime));
    return $time_str;
}

# favorites

sub get_favorites {
    my ( $self, $id ) = @_;
    return $Favorites{$id};
}


sub set_favorites {
    my ( $self, $id, $state ) = @_;

    if ($state) {
        $Favorites{$id} = 1;
    }
    else {
        undef $Favorites{$id} ;
    }
    return;
}

# etc

sub get_http {
    my ( $self, $req ) = @_;
    my $res;
    my $timeout = 0;

    eval {
        $SIG{'ALRM'} = sub { $timeout = 1 };
        alarm 30;

        $res = $ua->request($req);
        alarm 0;
    };

    alarm 0;

    return ( $res, $timeout );
}

sub _hex2rgb {
    my $hex = shift;

    ( $_ = $hex ) =~ tr/#//d;
    my @colors = m/(\w{2})(\w{2})(\w{2})/;
    my ( $red, $green, $blue ) = map { hex($_) } @colors;

    return ( $red, $green, $blue );
}

sub _l10n {
    my ( $self, $text ) = @_;
    return $L10N->($text);
}

sub _message {
    my ( $self, $arg_ref ) = @_;

    my $timestr = $self->get_formatted_time( $arg_ref->{'unixtime'} );
    printf "(%s) %s: %s\n", $timestr, $arg_ref->{'user_id'},
        $arg_ref->{'body'};
}

sub _error {
    my ( $self, $desc, $text, $optional_desc ) = @_;

    return if !defined $text;
    $text = sprintf $self->_l10n("%s Error: %s"), $desc, $text;
    warn "$text\n";
}

1;
